package com.pxl.springbootinit.websocket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.pxl.springbootinit.model.entity.ChatMessage;
import com.pxl.springbootinit.service.ChatMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

@Service
@ServerEndpoint("/chat/{sid}")
public class WebSocketChatServer {

    public static ChatMessageService chatMessageService;

    @Resource
    public void setChatMessageService(ChatMessageService chatMessageService) {
        WebSocketChatServer.chatMessageService = chatMessageService;
    }

    private Session session;  // 每个连接的 Session
    private static ConcurrentHashMap<String, WebSocketChatServer> userSessions = new ConcurrentHashMap<>();
    private static int onlineCount = 0;
    private String sid = ""; // 存储每个连接的 sid

    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) throws IOException {
        this.session = session;
        this.sid = sid; // 使用 URL 中的 sid 参数为当前连接设置 sid
        userSessions.put(sid, this); // 将当前连接添加到 userSessions 映射中
        incrementOnlineCount(); // 增加在线连接数
        sendMessage("conn_success"); // 向客户端发送连接成功消息
        System.out.println("有新窗口开始监听:" + sid + ", 当前在线人数为:" + getOnlineCount());
    }

    @OnClose
    public void onClose() {
        userSessions.remove(this.sid); // 从 userSessions 中移除当前连接
        decrementOnlineCount(); // 减少在线连接数
        System.out.println("有一连接关闭！当前在线人数为 " + getOnlineCount());
    }

    @OnMessage
    public void onMessage(@RequestBody String message, Session session) {
        System.out.println("收到来自窗口 " + sid + " 的信息: " + message);
        JSONObject jsonObject = new JSONObject(message);

        // 获取各个字段
        String senderId = jsonObject.getStr("senderId");
        String content = jsonObject.getStr("content");
        String receiverId = jsonObject.getStr("receiverId");
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setMessage(content);
        chatMessage.setSenderId(Long.parseLong(senderId));
        chatMessage.setReceiverId(Long.parseLong(receiverId));
        sendPrivateMessage(receiverId, chatMessage); // 发送私聊消息
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }


    private void sendPrivateMessage(String targetSid, ChatMessage message) {
        WebSocketChatServer targetUser = userSessions.get(targetSid);
        if (targetUser != null) {
            try {
                String str = JSONUtil.toJsonStr(message);
                targetUser.sendMessage(str); // 发送私聊消息给目标用户
                this.sendMessage("私聊消息已发送给 " + targetSid + ": " + str); // 向发送者确认
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                this.sendMessage("目标用户 " + targetSid + " 不在线！"); // 如果目标用户不在线，向发送者反馈
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        chatMessageService.save(message); // 保存聊天记录
    }

    private void sendMessage(String message) throws IOException {
        if (this.session != null && this.session.isOpen()) {
            this.session.getBasicRemote().sendText(message); // 发送消息
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void incrementOnlineCount() {
        WebSocketChatServer.onlineCount++;
    }

    public static synchronized void decrementOnlineCount() {
        WebSocketChatServer.onlineCount--;
    }

    // 群发消息
    public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException {
        for (WebSocketChatServer client : userSessions.values()) {
            if (sid == null || client.sid.equals(sid)) {
                client.sendMessage(message);
            }
        }
    }
}
